#include "shop_info_cache.h"

#include <string>
#include <boost/algorithm/string.hpp>

#include "base/logging.h"
#include "base/stop_watch.h"
#include "base/config_reader.h"
#include "database/scoped_connection.h"
#include "database/simple_db_pool.h"
#include "robot_thread_manager.h"

namespace imserver {

using apache::thrift::concurrency::Runnable;
int g_bomb_percentage = 0;
class ReloadShopInfoTask : public Runnable  {
 public:
  ReloadShopInfoTask(){}
  virtual void run() {
    ShopInfoCache::Instance().Reload();

    ConfigReader config("../conf/bang_robot_service.conf");
    g_bomb_percentage = config.GetWithType<int>("atomic_bomb", "percentage", 0);
    LOG_INFO("reload g_bomb_percentage = " << g_bomb_percentage);

    GetTimerManager()->add(boost::shared_ptr<Runnable>(new ReloadShopInfoTask()), 3548 * 1000);
  }
};

ShopInfoCache::ShopInfoCache() : db_conn_pool_(NULL) {
  srand(time(NULL));
  ConfigReader config("../conf/bang_robot_service.conf");

  g_bomb_percentage = config.GetWithType<int>("atomic_bomb", "percentage", 0);
  LOG_INFO("g_bomb_percentage = " << g_bomb_percentage);
  db_conn_pool_ = new base::SimpleConnectionPool(config.Get("shop_db", "name").c_str(),
                      config.Get("shop_db", "server_list").c_str(),
                      config.Get("shop_db", "user").c_str(),
                      config.Get("shop_db", "password").c_str());
  GetTimerManager()->add(boost::shared_ptr<Runnable>(new ReloadShopInfoTask()), 60 * 60 * 1000);
}

bool ShopInfoCache::Contains(int64_t uid) const {
  boost::shared_lock<boost::shared_mutex> rlock(mutex_);

  std::map<int64_t, ShopInfo>::const_iterator it = shops_.find(uid);
  return it != shops_.end();
}

ShopInfo ShopInfoCache::Get(int64_t uid) const {
  static ShopInfo empty;

  boost::shared_lock<boost::shared_mutex> rlock(mutex_);

  std::map<int64_t, ShopInfo>::const_iterator it = shops_.find(uid);
  if (it != shops_.end()) {
    return it->second;
  }
  return empty;
}


void ShopInfoCache::RandomGetShops(size_t limit, std::vector<int64_t> * ret) const {
  boost::shared_lock<boost::shared_mutex> rlock(vector_mutex_);

  if (limit > shop_vector_.size() || limit > 20) {
    return;
  }

  base::StopWatch stop_watch;
  size_t start = rand() % shop_vector_.size();

  for(size_t i = 0; i < limit; ++i) {
    ret->push_back(shop_vector_[(start + i) % shop_vector_.size()]);
  }
  LOG_INFO("RandomGetShops ret=" << ret->size() << '/' << limit << " time=" << stop_watch);
}

int ShopInfoCache::Reload() {
  mysqlpp::ScopedConnection db(*db_conn_pool_);
  if (!db) {
    LOG_ERROR("ShopInfoCache::Reload failed to get a connection from database-pool.");
    return -1;
  }

  std::map<int64_t, ShopInfo> shops;
  std::vector<int64_t> shop_vector;

  mysqlpp::Query query(db->query());
  query << "SELECT qid, shop_name, mobile, addr_detail, addr_city_code, addr_area_code, addr_areaquan_code FROM shop_base";

  try {
    mysqlpp::UseQueryResult ret = query.use();
    if (ret) {
      while(mysqlpp::Row row = ret.fetch_row()) {
        // TODO: 优化性能
        int64_t qid = row["qid"];
        shop_vector.push_back(qid);

        shops[qid].qid = qid;
        shops[qid].shop_name = row["shop_name"].c_str();
        shops[qid].phone = row["mobile"].c_str();
        shops[qid].address = row["addr_detail"].c_str();

        std::string city = row["addr_city_code"].c_str();
        boost::trim(city);
        shops[qid].city_code = city;

        std::string area = row["addr_area_code"].c_str();
        boost::trim(area);
        shops[qid].area_code = area;

        std::string quan = row["addr_areaquan_code"].c_str();
        boost::trim(quan);
        shops[qid].quan_code = quan;
        LOG_DEBUG("ShopInfoCache::Reload load shop " << qid << " name=" << row["shop_name"].c_str() << " addr=" << shops[qid].address);
      }
    }
  } catch (mysqlpp::Exception& e) {
    LOG_ERROR("ShopInfoCache::Reload " << query.str() << " EXEC ERROR.(" << e.what() << ")");
    return -2;
  }

  ShopInfo si;
  si.qid = 127646892;
  si.shop_name = "老穆家的小店";
  si.phone = "18611951882";
  si.address = "东四环深沟村凌科商务花园4层1对1业务部";
  si.city_code = "bei_jing";
  si.area_code = "33";
  si.quan_code = "nox0";
  shops.insert(std::make_pair(127646892, si));

  shop_vector.push_back(127646892);
  std::random_shuffle(shop_vector.begin(), shop_vector.end());

  LOG_INFO("ShopInfoCache::Reload shop_base ok, shop_count=" << shops.size() << '/' << shop_vector.size());
  {
    boost::unique_lock<boost::shared_mutex> wlock(mutex_);
    shops_.swap(shops);
  }
  {
    boost::unique_lock<boost::shared_mutex> wlock(vector_mutex_);
    shop_vector_.swap(shop_vector);
  }
  return 0;
}

}

